// $Id: interface.hpp 2 2009-09-02 08:47:42Z joseph2002 $
/*
 * Copyright 2008-2009 Joseph Wu
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 *
 * For more information, see http://xpcomplus.sourceforge.net
 */

#ifndef XPCOM_INTERFACE_HPP
#define XPCOM_INTERFACE_HPP

#include <xpcom/config.hpp>
#include <boost/mpl/void.hpp>
#include <xpcom/types.hpp>
#include <xpcom/type_info.hpp>

#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_PREFIX
#endif

namespace xpcom {

//
// Base for all XPCOM interfaces
// This class is compatible with mozilla's nsISupports class.
//
class XPCOM_NO_VTABLE interface
{
public:
    XPCOM_IMETHOD query_interface(const uuid& iid, void** obj) = 0;

    XPCOM_IMETHOD_(refcnt_t) add_ref() = 0;
    XPCOM_IMETHOD_(refcnt_t) release() = 0;

    template <typename T>
    XPCOM_METHOD query_interface(T** obj)
    {
        return query_interface(typeid_of<T>(), reinterpret_cast<void**>(obj));
    }
};

//
// type_info for interface
//
XPCOM_TYPE_INFO_DECL(interface, boost::mpl::void_)

// 00000000-0000-0000-C000-000000000046
XPCOM_TYPE_INFO_ID(interface,
    { 0x00000000, 0x0000, 0x0000,
    { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } })
XPCOM_TYPE_INFO_NAME(interface, "xpcom.interface")

//
// Compare two interface pointer for their underlying instance
//
XPCOM_DECL int interface_instance_compare(interface* p1, interface* p2);

inline bool interface_instance_equal(interface* p1, interface* p2)
{
    return interface_instance_compare(p1, p2) == 0;
}

// For boost::intrusive_ptr
inline void intrusive_ptr_add_ref(interface* p)
{
    p->add_ref();
}

inline void intrusive_ptr_release(interface* p)
{
    p->release();
}

} // namespace xpcom

#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_SUFFIX
#endif

#endif // XPCOM_INTERFACE_HPP
